package com.cqie.interceptor;

import com.cqie.dto.TokenUserLoginDto;
import com.cqie.threadlocal.UserThreadLocal;
import com.cqie.util.JwtTokenUtil;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;


@Slf4j
@Configuration
public class TokenInterceptor implements HandlerInterceptor {
    /**
     * 将cookie封装到Map里面
     *
     * @param request
     * @return
     */
    private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request) {
        // 创建一个空的HashMap，用于存储Cookie信息
        Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
        // 通过HttpServletRequest对象获取Cookie数组
        Cookie[] cookies = request.getCookies();
        // 输出Cookie数组，用于调试
        System.out.println(cookies);
        // 如果Cookie数组不为空
        if (null != cookies) {
            // 遍历Cookie数组
            for (Cookie cookie : cookies) {
                // 将每个Cookie对象存储在HashMap中，以Cookie的名称作为键，Cookie对象本身作为值
                cookieMap.put(cookie.getName(), cookie);
            }
        }
        // 输出存储Cookie信息的HashMap，用于调试
        System.out.println(cookieMap);
        // 返回存储Cookie信息的HashMap
        return cookieMap;
    }

    /**
     * 根据名字获取cookie
     *
     * @param request
     * @param name    cookie名字
     * @return
     */
    public static Cookie getCookieByName(HttpServletRequest request, String name) {
        Map<String, Cookie> cookieMap = ReadCookieMap(request);
        // 检查cookieMap中是否包含指定名称的Cookie
        if (cookieMap.containsKey(name)) {
            // 如果包含，则获取该Cookie并返回
            Cookie cookie = cookieMap.get(name);
            return cookie;
        } else {
            // 如果不包含，则返回null
            return null;
        }
    }

    /**
     * 从请求头中获取Token
     *
     * @param request
     * @return Token字符串，如果不存在则返回null
     */
    private static String getTokenFromHeader(HttpServletRequest request) {
        Enumeration<String> headers = request.getHeaders("Authorization");
        while (headers.hasMoreElements()) {
            String value = headers.nextElement();
            if (value.toLowerCase().startsWith("bearer ")) {
                return value.substring(7);
            }
        }
        return null;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从请求头中获取Token
        var token = getTokenFromHeader(request);
        response.setCharacterEncoding("utf-8");

        // 如果已经登录，不拦截
        if (StringUtils.hasText(token)) {
            //验证token是否正确
            log.info("获取的token------>" + token);


            TokenUserLoginDto tokenUserLoginDto = new TokenUserLoginDto();
            // 检查 token 前缀并解析
            if (token.startsWith("doctor:")) {
                //对token进行一些验证操作，并返回一个布尔值结果
                boolean result = JwtTokenUtil.verify(token.substring(7));

                if (!result) {
                    log.info("token失效 或 无效token");
                    throw new RuntimeException("token失效 或 无效token");
                }
                // 解析 doctor token
                 tokenUserLoginDto = JwtTokenUtil.getDoctorDto(token.substring(7));
            } else if (token.startsWith("patient:")) {
                //对token进行一些验证操作，并返回一个布尔值结果
                boolean result = JwtTokenUtil.verify(token.substring(8));

                if (!result) {
                    log.info("token失效 或 无效token");
                    throw new RuntimeException("token失效 或 无效token");
                }
                // 解析 patient token
                 tokenUserLoginDto = JwtTokenUtil.getPatientDto(token.substring(8));
            } else {
                // 无效的 token 前缀
                throw new RuntimeException("无效的 token 前缀");
            }

            // 将解析后的 token 信息存放到线程本地变量
            UserThreadLocal.set(tokenUserLoginDto);
            log.info("token 存放信息:" + tokenUserLoginDto);
            return true;
        }
        // 没有登录
        else {
            throw new RuntimeException("请先登录");
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception ex) throws Exception {
        //程序运行结束之后，删除线程，防止内存泄漏
        UserThreadLocal.remove();

    }

}